package com.asm.service;

import com.asm.dto.PageResult;
import com.asm.entity.sys.Book;
import com.asm.repository.BookRepository;
import com.asm.util.SnowflakeIdWorker;
import com.asm.vo.sys.BookVo;
import com.asm.vo.sys.ContractContainVo;
import com.asm.vo.sys.ContractVo;
import com.asm.vo.sys.WorkOrderVo;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author michael
 */
@Service
public class BookService {
    @Resource
    private BookRepository bookRepository;

    @Resource
    private ContractService contractService;

    @Resource
    private ContractContainService contractContainService;

    @Resource
    private UserService userService;

    @Resource
    private WorkOrderService workOrderService;

    @Resource
    private SnowflakeIdWorker snowflakeIdWorker;

    /**
     * 获取预定信息列表
     *
     * @param page 获取预定信息的对象
     * @return 存储预定信息的列表对象
     */
    private List<BookVo> getBookVoList(Page<Book> page) {
        List<BookVo> list = new ArrayList<>();
        for (Book book : page.getContent()) {
            BookVo bookVo = new BookVo();
            BeanUtils.copyProperties(book, bookVo);
            list.add(bookVo);
        }
        return list;
    }

    /**
     * 分页查询所有预定信息
     *
     * @param pageNumber 页码
     * @param pageSize   页大小
     * @return 用于实现分页效果的对象
     */
    public PageResult<BookVo> findAllBooks(Integer pageNumber, Integer pageSize) {
        List<Book> list1 = bookRepository.findByStatusAndIsDel("待审核", false);
        List<Book> list2 = bookRepository.findByStatusAndIsDel("待派发", false);
        List<Book> list3 = bookRepository.findByStatusAndIsDel("待安装", false);
        List<Book> list4 = bookRepository.findByStatusAndIsDel("安装完成", false);
        List<List<Book>> bookLists = new ArrayList<>();
        bookLists.add(list1);
        bookLists.add(list2);
        bookLists.add(list3);
        bookLists.add(list4);
        List<BookVo> bookVoList = new ArrayList<>();
        for (int i = 0; i < bookLists.size(); i++) {
            List<Book> list = bookLists.get(i);
            for (int j = 0; j < list.size(); j++) {
                BookVo bookVo = new BookVo();
                BeanUtils.copyProperties(list.get(j), bookVo);
                bookVoList.add(bookVo);
            }
        }
        List<BookVo> subList = null;
        int totalPages = bookVoList.size() / pageSize;
        if (bookVoList.size() % pageSize != 0) {
            totalPages++;
        }
        if (pageNumber >= 0 && pageNumber < totalPages) {
            int start = pageNumber * pageSize;
            int end = start + pageSize;
            if (pageNumber == totalPages - 1 && end > bookVoList.size()) {
                end = bookVoList.size();
            }
            subList = bookVoList.subList(start, end);
        }
        return new PageResult<>(pageNumber, pageSize, totalPages, subList);
    }

    /**
     * 根据id查询预定信息
     *
     * @param id 预定信息id
     * @return 预定信息的vo对象
     */
    public BookVo findBookById(Long id) {
        BookVo bookVo = new BookVo();
        if (bookRepository.findById(id).isPresent()) {
            Book book = bookRepository.findById(id).get();
            BeanUtils.copyProperties(book, bookVo);
        }
        return bookVo;
    }

    /**
     * 根据顾客id查询预定信息列表
     *
     * @param customerId 顾客id
     * @return 预定信息列表
     */
    public List<BookVo> findBookByCustomerId(Long customerId) {
        List<Book> temp = bookRepository.findByCustomerIdAndIsDel(customerId, false);
        List<BookVo> list = new ArrayList<>();
        for (Book b :
                temp) {
            BookVo bookVo = new BookVo();
            BeanUtils.copyProperties(b, bookVo);
            list.add(bookVo);
        }
        return list;
    }

    /**
     * 根据合同Id分页查询预定信息
     *
     * @param contractId 销售人员Id
     * @param pageNumber 页码
     * @param pageSize   页大小
     * @return 用于实现分页效果的对象
     */
    public PageResult<BookVo> findBookByContractId(Long contractId, Integer pageNumber, Integer pageSize) {
        Pageable page = PageRequest.of(pageNumber, pageSize);
        Page<Book> books = bookRepository.findByContractIdAndIsDel(contractId, false, page);
        return new PageResult<>(pageNumber, pageSize, books.getTotalPages(), getBookVoList(books));
    }

    /**
     * 添加预定信息
     *
     * @param bookVo 预定信息vo对象
     */
    @Transactional(rollbackFor = Exception.class)
    public Long addBook(BookVo bookVo) {
        Book book = new Book();
        BeanUtils.copyProperties(bookVo, book);
        book.setId(snowflakeIdWorker.nextId());
        book.setCreateAt(new Date());
        book.setCreateBy(1L);
        book.setUpdateAt(new Date());
        book.setUpdateBy(1L);
        bookRepository.save(book);
        return book.getId();
    }

    /**
     * 更新预定信息
     *
     * @param bookVo 预定信息vo对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateBook(BookVo bookVo) {
        Book book = bookRepository.findById(bookVo.getId()).get();
        BeanUtils.copyProperties(bookVo, book);
        book.setUpdateBy(1L);
        book.setUpdateAt(new Date());
        System.out.println(book.toString());
        bookRepository.save(book);
    }

    /**
     * 根据id删除预定信息
     *
     * @param id 预定信息id
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteBook(Long id) {
        Book book = bookRepository.findById(id).get();
        book.setIsDel(true);
        book.setUpdateBy(1L);
        book.setUpdateAt(new Date());
        bookRepository.save(book);
    }

    /**
     * 生成预定信息订阅广告位
     *
     * @param bookVo 预定信息
     * @return 响应信息
     */
    public void repairApply(BookVo bookVo) {
        bookVo.setStatus("待审核");
        this.addBook(bookVo);
    }

    /**
     * 管理员审批通过，并创建工单等待工人维修
     *
     * @param bookVo 合同信息
     * @return 相应信息
     */
    public void applyConfirm(BookVo bookVo) {
        Book book = bookRepository.findByIdAndIsDel(bookVo.getId(), false);
        book.setSellId(bookVo.getSellId());
        BeanUtils.copyProperties(book, bookVo);
        WorkOrderVo workOrderVo = new WorkOrderVo();
        workOrderVo.setOrderId(bookVo.getId());
        workOrderVo.setStatus("未完成");
        workOrderVo.setWorkType("安装单");
        Long workOrderId = workOrderService.addWorkOrder(workOrderVo);
        bookVo.setWorkOrderId(workOrderId);

        ContractVo contractVo = new ContractVo();
        contractVo.setContractName("预定信息id：" + bookVo.getId());
        contractVo.setContractContent("合同内容：");
        contractVo.setContractDate(bookVo.getStartDate());
        contractVo.setContractEndDate(bookVo.getEndDate());
        Long contractId = contractService.addContract(contractVo);
        ContractContainVo contractContainVo = new ContractContainVo();
        contractContainVo.setSpotId(bookVo.getSpotId());
        contractContainVo.setContractId(contractId);
        contractContainService.addContractContain(contractContainVo);

        bookVo.setContractId(contractId);
        bookVo.setStatus("待派发");
        this.updateBook(bookVo);
    }

    /**
     * 随机派遣一名工人去安装广告
     *
     * @param bookVo 预定信息
     * @return 响应信息
     */
    public void assignTask(BookVo bookVo) {
        WorkOrderVo workOrderVo = workOrderService.findWorkOrderById(bookVo.getWorkOrderId());
        List<Map<String, Object>> workers = userService.findUserByRoleCode("worker");
        Random random = new Random(workers.size());
        int index = random.nextInt(workers.size());
        Map<String, Object> worker = workers.get(index);
        workOrderVo.setWorkerId((Long) worker.get("userId"));
        workOrderService.updateWorkOrder(workOrderVo);
        bookVo.setWorkOrderId(workOrderVo.getId());
        bookVo.setStatus("待安装");
        this.updateBook(bookVo);
    }

    /**
     * 管理员撤销预定申请
     *
     * @param bookVo 预定信息
     * @return 响应信息
     */
    public void applyCancel(BookVo bookVo) {
        this.deleteBook(bookVo.getId());
    }

}
